/**
 * 
 */
package z.tool.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author zhengll
 *
 */
public final class CollectionUtil {
    @SuppressWarnings("unchecked")
    private static <T> Map<String, List<T>> innerExtractFieldsValues(Class<T> clazz, boolean differentResult, Collection<?> coll, String... fields) {
        Map<String, List<T>> result = null;
        
        if (!ZUtils.isEmpty(coll) && !ZUtils.isEmpty(fields)) {
            result = ZUtils.newHashMap();
            if (differentResult) {
                for (String field : fields) {
                    result.put(field, new ArrayList<T>());
                }
            } else {
                List<T> list = new ArrayList<T>();
                for (String field : fields) {
                    result.put(field, list);
                }
            }
            
            Iterator<?> it = coll.iterator();
            Object first = it.next();
            
            // 获取field对应的getter method
            Method[] methods = new Method[fields.length];
            int index = 0;
            for (String field : fields) {
                try {
                    methods[index++] = first.getClass().getMethod("get" + ZUtils.capitalize(field));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            
            // 从第一个object中获取field values
            for (int i = 0; i < fields.length; i++) {
                try {
                    T t = (T)methods[i].invoke(first);
                    if (null != t) {
                        result.get(fields[i]).add(t);
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            
            // 从余下的ojbect中获取field values
            while (it.hasNext()) {
                first = it.next();
                for (int i = 0; i < fields.length; i++) {
                    try {
                        T t = (T)methods[i].invoke(first);
                        if (null != t) {
                            result.get(fields[i]).add(t);
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        
        return result;
    }
    
    public static <T>List<T> extractFieldsValues(Class<T> clazz, Collection<?> coll, String... fields) {
        Map<String, List<T>> result = innerExtractFieldsValues(clazz, false, coll, fields);
        return null != result && result.size() > 0 ? result.get(fields[0]) : null;
    }
    
    public static <T>Map<String, List<T>> extractDifferentFieldsValues(Class<T> clazz, Collection<?> coll, String... fields) {
        return innerExtractFieldsValues(clazz, true, coll, fields);
    }
    
}
